//#include "gd32f1x0.h"
#include "aoi.h"
#include "bb.h"
#include "bb_i2c_master.h"
#include "bsp.h"
#include "gd32f1x0.h"
#include "memory.h"
#include "plantform_systick.h"
#include <stdlib.h>

extern struct LCD lcd;

void _nop_(void)
{
	delay_us(2);
}

void delay_ss(uint32_t n)
{
	delay_ms(n * 1000);
}

/***************************************************


		port from origin project


***************************************************/

/***************************************************


		external functions implement


***************************************************/
#include "bb_i2c_master.h"

struct bb_i2c_master_initial_typedef bb_init;

struct bb_i2c_master i2c;

void lcm_reset(void)
{
}

#define _I2C_SDA_PORT GPIOA
#define _I2C_SDA_Pin GPIO_PIN_0

#define _I2C_SCL_PORT GPIOA
#define _I2C_SCL_Pin GPIO_PIN_1

static uint8_t _i2c_sda_get(void)
{
	// uint8_t r = gpio_output_bit_get(_I2C_SDA_PORT, _I2C_SDA_Pin);
	uint8_t r = gpio_input_bit_get(_I2C_SDA_PORT, _I2C_SDA_Pin);
	if (r == RESET) {
		return 0;
	} else {
		return 1;
	}
}

static uint8_t _i2c_scl_get(void)
{
	// uint8_t r = gpio_output_bit_get(_I2C_SCL_PORT, _I2C_SCL_Pin);
	uint8_t r = gpio_input_bit_get(_I2C_SCL_PORT, _I2C_SCL_Pin);
	if (r == RESET) {
		return 0;
	} else {
		return 1;
	}
}

static void _i2c_sda_set(uint8_t state)
{
	// state ? (gpio_bit_set(_I2C_SDA_PORT, _I2C_SDA_Pin)) : (gpio_bit_reset(_I2C_SDA_PORT, _I2C_SDA_Pin));
	if (state) {
		gpio_bit_set(_I2C_SDA_PORT, _I2C_SDA_Pin);
	} else {
		gpio_bit_reset(_I2C_SDA_PORT, _I2C_SDA_Pin);
	}
}

static void _i2c_scl_set(uint8_t state)
{
	// state ? (gpio_bit_set(_I2C_SDA_PORT, _I2C_SDA_Pin)) : (gpio_bit_reset(_I2C_SDA_PORT, _I2C_SDA_Pin));
	if (state) {
		gpio_bit_set(_I2C_SCL_PORT, _I2C_SCL_Pin);
	} else {
		gpio_bit_reset(_I2C_SCL_PORT, _I2C_SCL_Pin);
	}
}

#define data_len 40
#define addr_w 0x70

uint8_t buffer[data_len];

uint8_t header[] = {
    0x80,
    0xE0,
    0xF8,
    0xF0,
    0x00,
    0xc8,
};

uint8_t tail[] = {
    0xc8
};

static void lcm_io_initial(void)
{
	// IO initial
	gpio_mode_set(_I2C_SDA_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, _I2C_SDA_Pin);
	gpio_output_options_set(_I2C_SDA_PORT, GPIO_OTYPE_OD, GPIO_OSPEED_10MHZ, _I2C_SDA_Pin);

	gpio_mode_set(_I2C_SCL_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, _I2C_SCL_Pin);
	gpio_output_options_set(_I2C_SCL_PORT, GPIO_OTYPE_OD, GPIO_OSPEED_10MHZ, _I2C_SCL_Pin);
}

static void lcm_initial(void)
{
	bb_init._delay_us = delay_us;
	bb_init.speed = 100000;
	bb_init.scl_get = _i2c_scl_get;
	bb_init.sda_get = _i2c_sda_get;
	bb_init.scl_set = _i2c_scl_set;
	bb_init.sda_set = _i2c_sda_set;

	// i2c initial
	bb_i2c_master_initial(&i2c, &bb_init);

	//bb_i2c_slave_detect(&i2c);

	delay_ms(20);
}

__weak_symbol void fill_ram_with_data(uint8_t *pack, uint8_t *dat, uint32_t len)
{

}

static void fill_ram_with_byte(uint8_t B)
{
	int total_len = sizeof(header) + data_len + sizeof(tail);

	uint8_t *pack = malloc(total_len);

	for(int i =0; i< data_len; i++) {
		buffer[i] = B;
	}
	
	memcpy(pack, header, sizeof(header));
	memcpy(pack+sizeof(header), buffer, data_len);
	memcpy(pack+sizeof(header)+data_len, tail, sizeof(tail));

	bb_i2c_master_send(&i2c, addr_w, pack, total_len);
	free(pack);
}

__weak_symbol void refresh_display(void)
{

}

static void lcm_full(void)
{
	fill_ram_with_byte(0xFF);
}

static void lcm_clear(void)
{
	fill_ram_with_byte(0x00);
}

static void lcm_row_even(void)
{
	fill_ram_with_byte(0xaa);
}

static void lcm_row_odd(void)
{
	fill_ram_with_byte(0x55);
}

static void lcm_column_odd(void)
{
	fill_ram_with_byte(0xF0);
}

static void lcm_column_even(void)
{
	fill_ram_with_byte(0x0F);
}

static void lcm_main(void)
{
}

void aoi_config(void)
{
	lcd.io_initial = lcm_io_initial;
	lcd.test = lcm_main;
	lcd.reset = lcm_reset;
	lcd.initial = lcm_initial;
	lcd.screen[0] = lcm_clear;
	lcd.screen[1] = lcm_column_even;
	lcd.screen[2] = lcm_column_odd;
	lcd.screen[3] = lcm_row_even;
	lcd.screen[4] = lcm_row_odd;
	lcd.screen[0xf] = lcm_full;
}
